using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using FreeSql;
using XUCore.Ddd.Domain;
using XUCore.NetCore.FreeSql.Entity;
using XUCore.Paging;
using XUCore.Extensions;

namespace XUCore.NetCore.FreeSql.Curd
{
    /// <summary>
    /// CurdEntity
    /// </summary>
    /// <typeparam name="TKey">主键类型</typeparam>
    /// <typeparam name="TEntity">表实体</typeparam>
    public class CurdEntity<TKey, TEntity>
        where TEntity : class, IEntity<TKey>, new()
    {
        public readonly IFreeSql FreeSql;
        public readonly IBaseRepository<TEntity> Repo;
        public readonly IMapper Mapper;

        public CurdEntity(FreeSqlUnitOfWorkManager db, IMapper mapper)
            : this(db.Orm, mapper)
        {
            db.Binding(this.Repo);
        }
        public CurdEntity(IFreeSql free, IMapper mapper)
        {
            this.FreeSql = free;
            this.Mapper = mapper;
            this.Repo = FreeSql.GetRepository<TEntity>();
        }
        /// <summary>
        /// 查询对象
        /// </summary>
        public ISelect<TEntity> Select => Repo.Select;
        /// <summary>
        /// 更新对象
        /// </summary>
        public IUpdate<TEntity> Update => Repo.UpdateDiy;
        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IBaseRepository<T> Switch<T>() where T : class, new() => FreeSql.GetRepository<T>();
        /// <summary>
        /// 创建新的CurdEntity
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public CurdEntity<K, T> Create<K, T>() where T : class, IEntity<K>, new() => new CurdEntity<K, T>(FreeSql, Mapper);
        /// <summary>
        /// 创建新的CurdEntity
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public CurdEntity<TKey, T> Create<T>() where T : class, IEntity<TKey>, new() => new CurdEntity<TKey, T>(FreeSql, Mapper);
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> CreateAsync<TDto>(TEntity entity, CancellationToken cancellationToken = default)
            where TDto : class, new()
        {
            var res = await Repo.InsertAsync(entity, cancellationToken);

            return Mapper.Map<TDto>(res);
        }
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> CreateAsync(TEntity entity, CancellationToken cancellationToken = default)
        {
            return await Repo.InsertAsync(entity, cancellationToken);
        }
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TDto>> CreateAsync<TDto>(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
            where TDto : class, new()
        {
            var res = await Repo.InsertAsync(entities, cancellationToken);

            return Mapper.Map<List<TDto>>(res);
        }
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TEntity>> CreateAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
        {
            return await Repo.InsertAsync(entities, cancellationToken);
        }
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> CreateAsync<TCreateCommand, TDto>(TCreateCommand request, CancellationToken cancellationToken = default)
            where TCreateCommand : CreateCommand
            where TDto : class, new()
        {
            var entity = Mapper.Map<TCreateCommand, TEntity>(request);

            var res = await Repo.InsertAsync(entity, cancellationToken);

            return Mapper.Map<TDto>(res);
        }
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="requests"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TDto>> CreateAsync<TCreateCommand, TDto>(List<TCreateCommand> requests, CancellationToken cancellationToken = default)
            where TCreateCommand : CreateCommand
            where TDto : class, new()
        {
            var entities = Mapper.Map<List<TCreateCommand>, List<TEntity>>(requests);

            var res = await Repo.InsertAsync(entities, cancellationToken);

            return Mapper.Map<List<TDto>>(res);
        }
        /// <summary>
        /// 重建数据
        /// </summary>
        /// <param name="removeExp">删除的条件</param>
        /// <param name="entities">新写入的数据集合</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<TEntity>> RebuildAsync(Expression<Func<TEntity, bool>> removeExp, IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
        {
            if (removeExp != null)
                await Repo.DeleteAsync(removeExp, cancellationToken);

            if (entities != null && entities.Count() > 0)
                return await Repo.InsertAsync(entities, cancellationToken);

            return default;
        }
        /// <summary>
        /// 重建数据
        /// </summary>
        /// <param name="removeExp">删除的条件</param>
        /// <param name="keys">id集合</param>
        /// <param name="converter">数据转换</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<TEntity>> RebuildAsync(Expression<Func<TEntity, bool>> removeExp, IEnumerable<TKey> keys, Func<TKey, TEntity> converter, CancellationToken cancellationToken = default)
        {
            return await RebuildAsync(removeExp, keys?.ToMap(converter), cancellationToken);
        }
        /// <summary>
        /// 重建数据（处理关联表）
        /// </summary>
        /// <param name="removeExp">删除的条件</param>
        /// <param name="entities">新写入的数据集合</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<T>> RebuildAsync<T>(Expression<Func<T, bool>> removeExp, IEnumerable<T> entities, CancellationToken cancellationToken = default)
            where T : class, new()
        {
            var repo = Switch<T>();

            if (removeExp != null)
                await repo.DeleteAsync(removeExp, cancellationToken);

            if (entities != null && entities.Count() > 0)
                return await repo.InsertAsync(entities, cancellationToken);

            return default;
        }
        /// <summary>
        /// 重建数据（处理关联表）
        /// </summary>
        /// <param name="removeExp">删除的条件</param>
        /// <param name="keys">id集合</param>
        /// <param name="converter">数据转换</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<T>> RebuildAsync<K, T>(Expression<Func<T, bool>> removeExp, IEnumerable<K> keys, Func<K, T> converter, CancellationToken cancellationToken = default)
            where T : class, new()
        {
            return await RebuildAsync<T>(removeExp, keys?.ToMap(converter), cancellationToken);
        }
        /// <summary>
        /// 添加关联表数据
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<T>> CreateAsync<T>(IEnumerable<T> entities, CancellationToken cancellationToken = default)
            where T : class, new()
        {
            var repo = Switch<T>();

            return await repo.InsertAsync(entities, cancellationToken);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
        {
            return await Repo.UpdateAsync(entity, cancellationToken);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
        {
            return await Repo.UpdateAsync(entities, cancellationToken);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsync<TUpdateCommand>(TUpdateCommand request, CancellationToken cancellationToken = default)
            where TUpdateCommand : UpdateCommand<TKey>
        {
            var entity = await Select.WhereDynamic(request.Id).ToOneAsync(cancellationToken);

            if (entity == null) return 0;

            entity = Mapper.Map(request, entity);

            return await Repo.UpdateAsync(entity, cancellationToken);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="key">主键</param>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsync<TCommandMap>(TKey key, TCommandMap request, CancellationToken cancellationToken = default)
            where TCommandMap : CommandMap<TEntity>
        {
            var entity = await Select.WhereDynamic(key).ToOneAsync(cancellationToken);

            if (entity == null) return 0;

            entity = Mapper.Map(request, entity);

            return await Repo.UpdateAsync(entity, cancellationToken);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="exp">查询条件</param>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateAsync<TCommandMap>(Expression<Func<TEntity, bool>> exp, TCommandMap request, CancellationToken cancellationToken = default)
            where TCommandMap : CommandMap<TEntity>
        {
            var entity = await Select.Where(exp).ToOneAsync(cancellationToken);

            if (entity == null) return 0;

            entity = Mapper.Map(request, entity);

            return await Repo.UpdateAsync(entity, cancellationToken);
        }
        /// <summary>
        /// 设置更新的列<para></para>
        ///     注意：标记 [Column(CanUpdate = false)] 的属性不会被更新
        /// </summary>
        /// <param name="id"></param>
        /// <param name="field">字段名 nameof(TEntity.Name)</param>
        /// <param name="value">字段值</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> UpdateFieldAsync(TKey id, string field, object value, CancellationToken cancellationToken = default)
            => await UpdateFieldAsync(new TKey[] { id }, field, value, cancellationToken);
        /// <summary>
        /// 设置更新的列<para></para>
        ///     注意：标记 [Column(CanUpdate = false)] 的属性不会被更新<para></para>
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="field">字段名 nameof(TEntity.Name)</param>
        /// <param name="value">字段值</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> UpdateFieldAsync(TKey[] ids, string field, object value, CancellationToken cancellationToken = default)
            => await UpdateFieldAsync(c => ids.Contains(c.Id), field, value, cancellationToken);
        /// <summary>
        /// 设置更新的列<para></para>
        ///     注意：标记 [Column(CanUpdate = false)] 的属性不会被更新<para></para>
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="field">字段名 nameof(TEntity.Name)</param>
        /// <param name="value">字段值</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> UpdateFieldAsync(Expression<Func<TEntity, bool>> exp, string field, object value, CancellationToken cancellationToken = default)
        {
            var keyValues = new Dictionary<string, object>
            {
                { field, value }
            };

            return await UpdateFieldAsync(exp, keyValues, cancellationToken);
        }
        /// <summary>
        /// 设置更新的列<para></para>
        ///     注意：标记 [Column(CanUpdate = false)] 的属性不会被更新<para></para>
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="keyValues">var keyValues = new Dictionary&lt;string, object&gt;{ { "field1", 1 } , { "field2", "test" } };</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> UpdateFieldAsync(Expression<Func<TEntity, bool>> exp, Dictionary<string, object> keyValues, CancellationToken cancellationToken = default)
        {
            return await Update.Where(exp)
                .SetDto(keyValues)
                .ExecuteAffrowsAsync(cancellationToken);
        }
        /// <summary>
        /// 设置列的新值为基础上增加，格式：Set(a => a.Clicks + 1) 相当于 clicks=clicks+1<para></para>
        ///     指定更新，格式：Set(a => new T { Clicks = a.Clicks + 1, Time = DateTime.Now }) 相当于 set<para></para>
        ///     clicks=clicks+1,time='2019-06-19....'
        /// </summary>
        /// <param name="id"></param>
        /// <param name="column"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TMember"></typeparam>
        /// <returns></returns>
        public async Task<int> UpdateFieldAsync<TMember>(TKey id, Expression<Func<TEntity, TMember>> column, CancellationToken cancellationToken = default)
            => await UpdateFieldAsync(c => c.Id.Equals(id), column, cancellationToken);
        /// <summary>
        /// 设置列的新值为基础上增加，格式：Set(a => a.Clicks + 1) 相当于 clicks=clicks+1<para></para>
        ///     指定更新，格式：Set(a => new T { Clicks = a.Clicks + 1, Time = DateTime.Now }) 相当于 set<para></para>
        ///     clicks=clicks+1,time='2019-06-19....'
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="column"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TMember"></typeparam>
        /// <returns></returns>
        public async Task<int> UpdateFieldAsync<TMember>(TKey[] ids, Expression<Func<TEntity, TMember>> column, CancellationToken cancellationToken = default)
            => await UpdateFieldAsync(c => ids.Contains(c.Id), column, cancellationToken);
        /// <summary>
        /// 设置列的新值为基础上增加，格式：Set(a => a.Clicks + 1) 相当于 clicks=clicks+1<para></para>
        ///     指定更新，格式：Set(a => new T { Clicks = a.Clicks + 1, Time = DateTime.Now }) 相当于 set<para></para>
        ///     clicks=clicks+1,time='2019-06-19....'
        /// </summary>
        /// <param name="exp">需要更新的条件</param>
        /// <param name="column"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TMember"></typeparam>
        /// <returns></returns>
        public virtual async Task<int> UpdateFieldAsync<TMember>(Expression<Func<TEntity, bool>> exp, Expression<Func<TEntity, TMember>> column, CancellationToken cancellationToken = default)
        {
            return await Update.Where(exp)
                .Set(column)
                .ExecuteAffrowsAsync(cancellationToken);
        }
        /// <summary>
        /// 物理删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(TKey id, CancellationToken cancellationToken = default)
            => await DeleteAsync(c => c.Id.Equals(id), cancellationToken);
        /// <summary>
        /// 物理删除数据
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(TKey[] ids, CancellationToken cancellationToken = default)
            => await DeleteAsync(c => ids.Contains(c.Id), cancellationToken);
        /// <summary>
        /// 物理删除数据
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken = default)
            => await Repo.DeleteAsync(exp, cancellationToken);
        /// <summary>
        /// 删除数据（关联表）
        /// </summary>
        /// <param name="exp">删除的条件</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> DeleteAsync<T>(Expression<Func<T, bool>> exp, CancellationToken cancellationToken = default)
            where T : class, IEntity<TKey>, new()
        {
            return await Repo.Orm.Select<T>().Where(exp).ToDelete().ExecuteAffrowsAsync(cancellationToken);
        }
        /// <summary>
        /// 查询是否存在
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public virtual bool Any(Expression<Func<TEntity, bool>> exp)
            => Repo.Select.Any(exp);
        /// <summary>
        /// 查询是否存在
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken)
            => await Repo.Select.AnyAsync(exp, cancellationToken);
        /// <summary>
        /// 查询数据库总记录数
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public virtual long Count(Expression<Func<TEntity, bool>> exp)
            => Repo.Select.Where(exp).Count();
        /// <summary>
        /// 查询数据库总记录数
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<long> CountAsync(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken)
            => await Repo.Select.Where(exp).CountAsync(cancellationToken);
        /// <summary>
        /// 根据id获取一条记录
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> GetAsync<TDto>(TKey id, CancellationToken cancellationToken = default)
            where TDto : class, new()
        {
            var res = await Select.WhereDynamic(id).ToOneAsync(cancellationToken);

            return Mapper.Map<TEntity, TDto>(res);
        }
        /// <summary>
        /// 根据id获取一条记录
        /// </summary>
        /// <param name="id"></param>
        /// <param name="select">指定返回的数据字段信息</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TReturn> GetAsync<TReturn>(TKey id, Expression<Func<TEntity, TReturn>> select, CancellationToken cancellationToken = default)
            => await Select.WhereDynamic(id).ToOneAsync(select, cancellationToken);
        /// <summary>
        /// 根据条件获取一条记录
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> GetAsync<TDto>(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken = default)
            where TDto : class, new()
        {
            var res = await Select.Where(exp).ToOneAsync(cancellationToken);

            return Mapper.Map<TEntity, TDto>(res);
        }
        /// <summary>
        /// 根据条件获取一条记录
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken = default)
        {
            return await Select.Where(exp).ToOneAsync(cancellationToken);
        }
        /// <summary>
        /// 根据条件获取一条记录
        /// </summary>
        /// <param name="where"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> GetAsync<TDto>(Func<ISelect<TEntity>, ISelect<TEntity>> where, CancellationToken cancellationToken = default)
            where TDto : class, new()
        {
            var s = where(Select);

            var res = await s.ToOneAsync(cancellationToken);

            return Mapper.Map<TEntity, TDto>(res);
        }
        /// <summary>
        /// 根据条件获取一条记录
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="select">指定返回的数据字段信息</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TReturn> GetAsync<TReturn>(Expression<Func<TEntity, bool>> exp, Expression<Func<TEntity, TReturn>> select, CancellationToken cancellationToken = default)
            => await Select.Where(exp).ToOneAsync(select, cancellationToken);
        /// <summary>
        /// 根据条件获取一条记录
        /// </summary>
        /// <param name="where"></param>
        /// <param name="select">指定返回的数据字段信息</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TReturn> GetAsync<TReturn>(Func<ISelect<TEntity>, ISelect<TEntity>> where, Expression<Func<TEntity, TReturn>> select, CancellationToken cancellationToken = default)
        {
            var s = where(Select);

            return await s.ToOneAsync(select, cancellationToken);
        }
        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TDto>> GetListAsync<TDto>(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken = default)
        {
            var res = await Select.Where(exp).ToListAsync(cancellationToken);

            return Mapper.Map<List<TEntity>, List<TDto>>(res);
        }
        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> exp, CancellationToken cancellationToken = default)
        {
            return await Select.Where(exp).ToListAsync(cancellationToken);
        }
        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        /// <param name="where"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TDto>> GetListAsync<TDto>(Func<ISelect<TEntity>, ISelect<TEntity>> where, CancellationToken cancellationToken = default)
        {
            var s = where(Select);

            var res = await s.ToListAsync(cancellationToken);

            return Mapper.Map<List<TEntity>, List<TDto>>(res);
        }
        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        /// <param name="where"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TEntity>> GetListAsync(Func<ISelect<TEntity>, ISelect<TEntity>> where, CancellationToken cancellationToken = default)
        {
            var s = where(Select);

            return await s.ToListAsync(cancellationToken);
        }
        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="select">指定返回的数据字段信息</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TReturn>> GetListAsync<TReturn>(Expression<Func<TEntity, bool>> exp, Expression<Func<TEntity, TReturn>> select, CancellationToken cancellationToken = default)
            => await Select.Where(exp).ToListAsync(select, cancellationToken);
        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        /// <param name="where"></param>
        /// <param name="select">指定返回的数据字段信息</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<List<TReturn>> GetListAsync<TReturn>(Func<ISelect<TEntity>, ISelect<TEntity>> where, Expression<Func<TEntity, TReturn>> select, CancellationToken cancellationToken = default)
        {
            var s = where(Select);

            return await s.ToListAsync(select, cancellationToken);
        }
        /// <summary>
        /// 根据条件获取分页列表
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="currentPage">当前页码</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="select">指定返回的数据字段信息</param>
        /// <param name="defaultEndPage">默认false，且页码必须&lt;=0，在特殊需求上可以使用，比如评论需要保证顺序的情况下，默认最新评论显示最后一页</param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TReturn"></typeparam>
        /// <returns></returns>
        public virtual async Task<PagedModel<TReturn>> GetPageAsync<TReturn>(Func<ISelect<TEntity>, ISelect<TEntity>> where, int currentPage, int pageSize, Expression<Func<TEntity, TReturn>> select, bool defaultEndPage = false, CancellationToken cancellationToken = default)
        {
            var s = where(Select);

            var page = await s
                .ToPagedListAsync(currentPage, pageSize,
                    select: select,
                    defaultEndPage: defaultEndPage,
                    cancellationToken: cancellationToken);

            return page.ToModel();
        }
        /// <summary>
        /// 根据条件获取分页列表
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="currentPage">当前页码</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="includeNestedMembers">false: 返回 2级 Join 的数据；true: 返回所有层级深度 Join 的导航数据；</param>
        /// <param name="defaultEndPage">默认false，且页码必须&lt;=0，在特殊需求上可以使用，比如评论需要保证顺序的情况下，默认最新评论显示最后一页</param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TDto"></typeparam>
        /// <returns></returns>
        public virtual async Task<PagedModel<TDto>> GetPageAsync<TDto>(Func<ISelect<TEntity>, ISelect<TEntity>> where, int currentPage, int pageSize, bool includeNestedMembers = false, bool defaultEndPage = false, CancellationToken cancellationToken = default)
        {
            var s = where(Select);

            var page = await s
                .ToPagedListAsync(currentPage, pageSize,
                    includeNestedMembers: includeNestedMembers,
                    select: list => Mapper.Map<List<TEntity>, List<TDto>>(list),
                    defaultEndPage: defaultEndPage,
                    cancellationToken: cancellationToken);

            return page.ToModel();
        }

        /// <summary>
        /// 利用反射来判断对象是否包含某个属性
        /// </summary>
        /// <param name="propertyName">需要判断的属性</param>
        /// <returns>是否包含</returns>
        public virtual bool ContainProperty(string propertyName)
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                var _findedPropertyInfo = typeof(TEntity).GetProperty(propertyName);
                return _findedPropertyInfo != null;
            }
            return false;
        }
    }
}